前面描述了基于constexpr计算的值元编程和基于递归模板实例化的类型元编程，两项在现代C++中都有使用，涉及不同的方法来驱动计算。值元编程也可以通过递归模板实例化来驱动，C++11中引入constexpr函数之前，这是首选的机制。下面的代码使用递归实例化计算整数的平方根:

\hspace*{\fill} \\ %插入空行
\noindent
\textit{bridge/sqrt1.hpp}
\begin{lstlisting}[style=styleCXX]
// primary template to compute sqrt(N)
template<int N, int LO=1, int HI=N>
struct Sqrt {
	// compute the midpoint, rounded up
	static constexpr auto mid = (LO+HI+1)/2;
	// search a not too large value in a halved interval
	static constexpr auto value = (N<mid*mid) ? Sqrt<N,LO,mid-1>::value
	: Sqrt<N,mid,HI>::value;
};

// partial specialization for the case when LO equals HI
template<int N, int M>
struct Sqrt<N,M,M> {
	static constexpr auto value = M;
};
\end{lstlisting}

这个元程序使用了与第23.1.1节中整数平方根constexpr函数使用相同的算法，连续将已知包含平方根的区间减半。元函数的输入是非类型模板参数，跟踪区间边界的“局部变量”也改为非类型模板参数。显然，这是一种远不如constexpr函数友好的方法，但我们仍会分析这段代码，以检查它如何使用编译器的资源。

我们可以看到元编程的计算引擎可能有很多选择，这并不是可以考虑的唯一方面。相反，我们倾向于选择C++元编程解决方案必须在以下三个方面做出权衡:

\begin{itemize}
\item 
计算

\item 
反射

\item 
生成
\end{itemize}

反射是一种以编程方式检查程序特性的能力。生成是指为程序生成代码的能力。

已经看到了两个计算选项:递归实例化和constexpr计算，我们在类型特征中找到了部分解决方案(参见第19.6.1节)。尽管可用的特性支持相当多的高级模板技术，但远不能涵盖语言中反射功能所需的功能。给定一个类类型，应用程序希望以编程的方式探索该类的成员。当前的特性基于模板实例化，C++可以提供语言工具或“固有”库组件

\begin{tcolorbox}[colback=webgreen!5!white,colframe=webgreen!75!black]
\hspace*{0.75cm}C++标准库中提供的一些特性已经依赖于编译器的某些合作(通过非标准的“固有”操作符)。参见19.10节。
\end{tcolorbox}

生成在编译时包含反射信息的类模板实例，这种方法适合基于递归模板实例化的计算。但类模板实例占用大量编译器存储空间，而这些存储空间直到编译结束时才会释放(否则会导致编译时间大大增加)。另一种选择是引入一种新的标准类型来表示反射信息，该选择有望与“计算”维度的constexpr评估选项配对。17.9节讨论了这个选项(C++标准化委员会正在积极调研)。

第17.9节还展示了实现强大代码生成的未来方法。在现有C++语言中创建一个灵活的、通用的、开发者友好的代码生成机制，仍然是一个挑战。实例化模板是一种“代码生成”机制，编译器在扩展对内联小函数的调用方面已经足够可靠，这种机制可以用作代码生成的载体。这些观察结果正是上面DotProductT示例的基础，结合更强大的反射功能，现有技术已经可以完全实现元编程。











































